
import * as Cesium from "cesium";
import { HydrodynamicData } from './hydroData';
import { proj4548ToProj4326 } from './corrdinateProj.ts';



// 处理单个上传的dat文件
export async function GetTxtFileContent(file:any):Promise<string>{
    return new Promise((resolve, reject) => {
        // console.log("Function run ...");

        const reader = new FileReader();
        // 读取文件内容
        reader.onload = function(e) {
            try{
                const fileContent : string = e.target.result as string;

                resolve(fileContent);
            }catch(error){
                reject(error);
            }
        };
        // 读取文件为文本，不考虑开头的gbk编码的中文内容
        reader.readAsText(file);
    });
}

export function GetPolygonPointArray(fileContent:string){
    // 去掉首行无用数据
    const lines = fileContent.split('\n').slice(2); // 假设前两行是标题和表头，从第三行开始读取数据
    // console.log('读取的数据第一行:', lines[0]);

    // TODO:当前仅读取最左侧和最右侧数据。还需读取更加精细的水文界面顶点数据来建模
    let leftHydroData:  Array<HydrodynamicData> = [];
    let rightHydroData:  Array<HydrodynamicData> = [];

    let count_num = 0;
    lines.forEach(line => {
        if (line.trim() === '') return; // 跳过空行
    
        const values = line.split(/\s+/).map(value => value.trim());
        // console.log('values:', values);
        count_num++;
    
        // 文件中的数据格式严格按照提供的格式，每个字段依次对应
        const [
            , I, J, level, totalFlux, waterLevel, waterDepth, USpeed, VSpeed, WSpeed, flux, temperature, salinity, colorants, X, Y, Z, 
        ] = values;

        // 解析水文截面数据（以TIME_HYD）为例
        const hydrodynamicData = new HydrodynamicData(
            parseInt(I, 10),
            parseInt(J, 10),
            parseInt(level, 10),
            parseFloat(totalFlux),
            parseFloat(waterLevel),
            parseFloat(waterDepth),
            parseFloat(USpeed),
            parseFloat(VSpeed),
            parseFloat(WSpeed),
            parseFloat(flux),
            parseFloat(temperature),
            parseFloat(salinity),
            parseFloat(colorants),
            parseFloat(X),
            parseFloat(Y),
            parseFloat(Z)
        );

        // 读取dat中的数据
        if(count_num>=5 && count_num<=343){//河流水面最左侧
            if(count_num % 2 == 1){
                leftHydroData.push(hydrodynamicData);
            }
        }
        else if(count_num>=706 && count_num<=875){//河流水面最右侧
            rightHydroData.push(hydrodynamicData);
        }
        else{
            // 什么都不执行
        }

    });


    // console.log(`数据数量:左侧岸点个数 ${leftHydroData.length} 右侧岸点个数 ${rightHydroData.length} `);//170

    return CreatePolygonGraphic(leftHydroData, rightHydroData);

     
}

export function GetValueArrayImage(fileContent:string){
    // 去掉首行无用数据
    const lines = fileContent.split('\n').slice(2); // 假设前两行是标题和表头，从第三行开始读取数据
    // console.log('读取的数据第一行:', lines[0]);

    // TODO:读取更加精细的水文界面顶点数据来建模
    let leftHydroData:  Array<HydrodynamicData> = [];
    let rightHydroData:  Array<HydrodynamicData> = [];

    let count_num = 0;
    lines.forEach(line => {
        if (line.trim() === '') return; // 跳过空行
    
        const values = line.split(/\s+/).map(value => value.trim());
        // console.log('values:', values);
        count_num++;
    
        // 文件中的数据格式严格按照提供的格式，每个字段依次对应
        const [
            , I, J, level, totalFlux, waterLevel, waterDepth, USpeed, VSpeed, WSpeed, flux, temperature, salinity, colorants, X, Y, Z, 
        ] = values;

        // 解析水文截面数据（以TIME_HYD）为例
        const hydrodynamicData = new HydrodynamicData(
            parseInt(I, 10),
            parseInt(J, 10),
            parseInt(level, 10),
            parseFloat(totalFlux),
            parseFloat(waterLevel),
            parseFloat(waterDepth),
            parseFloat(USpeed),
            parseFloat(VSpeed),
            parseFloat(WSpeed),
            parseFloat(flux),
            parseFloat(temperature),
            parseFloat(salinity),
            parseFloat(colorants),
            parseFloat(X),
            parseFloat(Y),
            parseFloat(Z)
        );

        // 读取dat中的数据
        if(count_num>=5 && count_num<=343){//河流水面最左侧
            if(count_num % 2 == 1){
                leftHydroData.push(hydrodynamicData);
            }
        }
        else if(count_num>=706 && count_num<=875){//河流水面最右侧
            rightHydroData.push(hydrodynamicData);
        }
        else{
            // 什么都不执行
        }

    });


    // console.log(`数据数量:左侧岸点个数 ${leftHydroData.length} 右侧岸点个数 ${rightHydroData.length} `);//170

    return CreateValueImageMaterial(leftHydroData, rightHydroData);
}

function CreateValueImageMaterial(leftHydroData:Array<HydrodynamicData>, rightHydroData:Array<HydrodynamicData>){
    const pointCount = leftHydroData.length;

    let valueData = [];
    for(let i =0;i<pointCount;i++){
        valueData.push(leftHydroData[i].temperature);
    };

    for(let i =0;i<pointCount;i++){
        valueData.push(rightHydroData[i].temperature);
    };

    const imgSize = 128;
    return CreateMaterialFromData(imgSize,valueData);

    // return CreateImageFromData(imgSize,valueData);

}

function CreateMaterialFromData(imgSize:number,valueData:number[]){

    const size = imgSize; // 图像的尺寸为128x128
    const canvas = document.createElement('canvas');
    canvas.width = size;
    canvas.height = size;

    const ctx = canvas.getContext('2d');

    const imageData = ctx?.createImageData(size, size); // 创建一个size*size的图像数据
    // console.log("imageData length:",imageData?.data.length); size*size*4 的数组

    ValueData2ImageData(valueData,128,imageData);

    // console.log("ImageData:",imageData);

    // 将图像数据绘制到canvas上
    ctx?.putImageData(imageData, 0, 0);

    // NOTE:将图片下载至本地
    SaveImgPNG(canvas);
    // SaveImgJpeg(canvas);


    // 创建一个 Cesium.Material 从 canvas
    var material = new Cesium.ImageMaterialProperty({
        image: canvas,
        repeat: new Cesium.Cartesian2(1.0, 1.0),
        color: Cesium.Color.WHITE, // 可以根据需要调整颜色
        transparent: false
    });

    return material;

}

function ValueData2ImageData(valueData:number[],size:number,imageData:ImageData | undefined){
    // TODO:
    // 假设顶点的数量小size*size，所以我们按顺序将valueData.length个温度值映射到128x128的图像
    // 将温度数据映射到图像像素上
    for (let i = 0; i < valueData.length; i++) {
        const value = valueData[i]; // 获取顶点的温度

        // 计算这个温度值应该映射到图像的哪个像素位置
        const x = i % size; // 计算x坐标
        const y = Math.floor(i / size); // 计算y坐标

        const index = (y * size + x) * 4; // 获取像素在图像数据中的位置
        // const colorValue = Math.max(0, Math.min(255, value)); // 将温度值限制在0到255之间

        let color = Value2Color(value,0,25);
        // console.log("color:", color);

        // 将温度值映射到像素的RGB通道上，这里假设温度值存储在灰度图像中（r、g、b均存储相同值）
        imageData.data[index] = color[0];     // R
        imageData.data[index + 1] = color[1]; // G
        imageData.data[index + 2] = color[2]; // B
        imageData.data[index + 3] = 255;        // A

    }

    // console.log("ImageData:",imageData);
    // return imageData;
}

function CreateImageFromData(imgSize:number,valueData:number[]){

    const size = imgSize; // 图像的尺寸为128x128
    const canvas = document.createElement('canvas');
    canvas.width = size;
    canvas.height = size;

    const ctx = canvas.getContext('2d');

    const imageData = ctx?.createImageData(size, size); // 创建一个size*size的图像数据
    // console.log("imageData length:",imageData?.data.length); size*size*4 的数组

    ValueData2ImageData(valueData,128,imageData);
    
    // 将图像数据绘制到canvas上
    ctx?.putImageData(imageData, 0, 0);

    // NOTE:将图片下载至本地
    // SaveImgPNG(canvas);
    // SaveImgJpeg(canvas);


    return canvas;

}

// TODO：
function Value2Color(value:number,minValue:number,maxValue:number){


    const coldColor = [0.0,0.0,1.0];
    const hotColor = [1.0,0.0,0.0];

    let colorValue;
    
    // 手动指定色带 0-25 blue-red
    if (value < minValue) {
        colorValue = coldColor;
    } else if (value > maxValue) {
        colorValue = hotColor;
    }
    else {
        const ratio = value / (maxValue-minValue);
        colorValue = [
            coldColor[0] * (1 - ratio) + hotColor[0] * ratio * 255,
            coldColor[1] * (1 - ratio) + hotColor[1] * ratio * 255,
            coldColor[2] * (1 - ratio) + hotColor[2] * ratio * 255
        ]
    }
    return colorValue;

}


// 处理上传的单个水文文件
export async function ReadTextFileFromWeb(file:any):Promise<Array<number>>{
    return new Promise((resolve, reject) => {
        // console.log("Function run ...");

        const reader = new FileReader();
        // 读取文件内容
        reader.onload = function(e) {
            try{
                const fileContent : string = e.target.result as string;

                let points = DealThisDATFile(fileContent);

                resolve(points);
            }catch(error){
                reject(error);
            }
        };
        // 读取文件为文本，不考虑开头的gbk编码的中文内容
        reader.readAsText(file);
    });
}

// TODO:
// 处理上传的多份文件/处理文件夹
export async function ReadTextFileFromWebList(files:FileList):Promise<Three.Mesh[]>{
    return new Promise((resolve, reject) => {
        console.log("Function run ...");

        let meshList: Three.Mesh[] = [];

        for(let i=0;i<files.length;i++){
            const reader = new FileReader();
            // 读取文件内容
            reader.onload = function(e) {
                try{
                    const fileContent : string = e.target.result as string;

                    let mesh = DealThisDATFile(fileContent);
                    // console.log("mesh:", mesh);

                    meshList.push(mesh);
                }catch(error){
                    reject(error);
                }
            };
            // 读取文件为文本，不考虑开头的gbk编码的中文内容
            reader.readAsText(files[i]);
        }

        resolve(meshList);
    });
}

function DealThisDATFile(fileContent:string){
    // 去掉首行无用数据
    const lines = fileContent.split('\n').slice(2); // 假设前两行是标题和表头，从第三行开始读取数据
    // console.log('读取的数据第一行:', lines[0]);

    // TODO:读取更加精细的水文界面顶点数据来建模
    let leftHydroData:  Array<HydrodynamicData> = [];
    let rightHydroData:  Array<HydrodynamicData> = [];

    let count_num = 0;
    lines.forEach(line => {
        if (line.trim() === '') return; // 跳过空行
    
        const values = line.split(/\s+/).map(value => value.trim());
        // console.log('values:', values);
        count_num++;
    
        // 文件中的数据格式严格按照提供的格式，每个字段依次对应
        const [
            , I, J, level, totalFlux, waterLevel, waterDepth, USpeed, VSpeed, WSpeed, flux, temperature, salinity, colorants, X, Y, Z, 
        ] = values;
    
        const hydrodynamicData = new HydrodynamicData(
            parseInt(I, 10),
            parseInt(J, 10),
            parseInt(level, 10),
            parseFloat(totalFlux),
            parseFloat(waterLevel),
            parseFloat(waterDepth),
            parseFloat(USpeed),
            parseFloat(VSpeed),
            parseFloat(WSpeed),
            parseFloat(flux),
            parseFloat(temperature),
            parseFloat(salinity),
            parseFloat(colorants),
            parseFloat(X),
            parseFloat(Y),
            parseFloat(Z)
        );
        // 读取dat中的数据
        if(count_num>=5 && count_num<=343){//河流水面最左侧
            if(count_num % 2 == 1){
                leftHydroData.push(hydrodynamicData);
            }
        }
        else if(count_num>=706 && count_num<=875){//河流水面最右侧
            rightHydroData.push(hydrodynamicData);
        }
        else{
            // 什么都不执行
        }

    });
    
    // console.log('读取的河岸左侧数据第一行:', leftHydroData[0]);
    // console.log('读取的河岸左侧数据最后一行:', leftHydroData[leftHydroData.length-1]);
    // console.log('读取的河岸右侧数据第一行:', rightHydroData[0]);
    // console.log('读取的河岸右侧数据最后一行:', rightHydroData[rightHydroData.length-1]);
    // console.log('数据数量:', leftHydroData.length,rightHydroData.length);//170
    

    return CreatePolygonGraphic(leftHydroData, rightHydroData);

    
}

function CreatePolygonGraphic(leftHydroData:Array<HydrodynamicData>,rightHydroData:Array<HydrodynamicData>):number[]{
    const pointCount = leftHydroData.length;
    let leftPointWgs84 = [];
    let rightPointWgs84 = [];

    // NOTE:读取XYZ数据进行建模
    for(let i =0;i<pointCount;i++){
        leftPointWgs84.push(proj4548ToProj4326(leftHydroData[i].X, leftHydroData[i].Y));
        rightPointWgs84.push(proj4548ToProj4326(rightHydroData[i].X, rightHydroData[i].Y));

    }

    // console.log("左右点个数:",pointCount);//170

    // let vertexPoint = [...leftPointWgs84, ...rightPointWgs84];
    // console.log(`vertexPoint前四个数据:${vertexPoint[0]},${vertexPoint[1]},${vertexPoint[2]},${vertexPoint[3]}`);

    // 顺序存储左侧岸点和右侧岸点
    let outPointArray = [];
    for(let i=0;i<leftPointWgs84.length;i++){
        outPointArray.push(leftPointWgs84[i][0], leftPointWgs84[i][1]);
    }
    for(let i=1;i<=rightPointWgs84.length;i++){
        outPointArray.push(rightPointWgs84[pointCount-i][0], rightPointWgs84[pointCount-i][1]);
    }

    

    return outPointArray;

}

function SaveImgPNG(canvas:HTMLCanvasElement){
    const dataURL = canvas.toDataURL('image/png');
    
    // 创建一个链接元素，并设置其href属性为data URL
    const link = document.createElement('a');
    link.href = dataURL;
    
    // TODO:设置下载的文件名
    link.download = 'temperature_map.png';

    
    // 触发点击事件以下载文件
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    return;
}

function SaveImgJpeg(canvas:HTMLCanvasElement){
    // 将canvas内容转换为data URL，并指定格式为JPEG以及质量为0.9（高质量）
    const dataURL = canvas.toDataURL('image/jpeg', 0.9);

    // 创建一个链接元素，并设置其href属性为data URL
    const link = document.createElement('a');
    link.href = dataURL;

    // 设置下载的文件名为带有.jpg扩展名的名称
    link.download = 'temperature_map.jpg';


    
    // 触发点击事件以下载文件
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    return;
}